<?php

namespace SLN0001\DAO;

use Home\DAO\BizConfigDAO;
use Home\DAO\PSIBaseExDAO;
use SLN0002\DAO\AccCommDAO;

/**
 * 库存建账 DAO
 *
 * @author PSI
 * @copyright 2015 - present
 * @license GPL v3
 */
class InitInventoryDAO extends PSIBaseExDAO
{
  /**
   * 生成财务总账的明细分类账建账数据
   */
  public function genGlInitData(&$params)
  {
    $db = $this->db;

    $warehouseId = $params["id"];

    $sql = "select inited, name, org_id, code
            from t_warehouse
            where id = '%s' ";
    $data = $db->query($sql, $warehouseId);
    if (!$data) {
      return $this->badParam("id");
    }
    $warehouseName = $data["0"]["name"];
    $warehouseCode = $data["0"]["code"];
    $inited = $data[0]["inited"] == 1;
    if (!$inited) {
      return $this->bad("{$warehouseName}还没有建账完毕，其数据不能生成财务总账建账数据");
    }
    $companyId = $data[0]["org_id"];
    $sql = "select name, fi_inited_by_sln0001 
            from t_org 
            where id = '%s' ";
    $data = $db->query($sql, $companyId);
    if (!$data) {
      // 莫名的bug
      return $this->badParam("companyId");
    }
    $companyName = $data[0]["name"];
    $initedSubject = $data[0]["fi_inited_by_sln0001"] == 1;
    if (!$initedSubject) {
      // 初始化标准进销存账样，是通过会计科目里面的【一键初始化标准进销存账样】实现，该功能中会修改fi_inited_by_sln0001标志
      // 理论上说，不通过该功能也能设置符合标志进销存的账样，但是很难想象某个人会在提供了一键完成的前提下，用手工一个一个地完成账样的设置
      // 所以，就用fi_inited_by_sln0001这个标志来做判断了
      return $this->bad("{$companyName}还没有初始标准进销存账样");
    }

    // 检查对应的公司是否已经完成明细分类账建账了
    $sql = "select acc_year, acc_month, acc_detail_inited
            from t_acc_init
            where company_id";
    $data = $db->query($sql, $companyId);
    if (!$data) {
      return $this->bad("{$companyName}还没有初始会计期间");
    }
    $accDetailInited = $data[0]["acc_detail_inited"] == 1;
    if ($accDetailInited) {
      return $this->bad("{$companyName}已经完成明细分类账建账了，不能再由库存建账数据生成明细分类账建账数据");
    }
    $accYear = $data[0]["acc_year"];
    $accMonth = $data[0]["acc_month"];
    $daoCommon = new AccCommDAO($db);
    $accDT = $daoCommon->buildVoucherLastDT($accYear, $accMonth);

    $bcDAO = new BizConfigDAO($db);
    $dataScale = $bcDAO->getGoodsCountDecNumber($companyId);
    $fmt = "decimal(19, " . $dataScale . ")";

    // m_type = 5000: 虚拟件
    $sql = "select v.goods_id, convert(v.balance_count, $fmt) as balance_count, v.balance_price, 
              v.balance_money 
            from t_goods g, t_inventory_detail v 
            where g.m_type <> 5000
              and g.id = v.goods_id and v.ref_type = '库存建账' 
              and v.warehouse_id = '%s' 
            order by g.code";
    $dataInv = $db->query($sql, $warehouseId);
    if (!$dataInv) {
      return $this->bad("{$warehouseName}没有建账数据，无法生成财务总账的建账数据");
    }

    // 目前不检查库存建账的日期和财务总账的建账会计期间的关系
    // 如果是先实施进销存模板，后实施财务总账模块，则存在进销存模板的建账数据不符合财务总账建账数据的要求
    // 怎么解决这个问题，还没有好的方案

    $sql = "select db_table_name_prefix
            from t_acc_fmt
            where company_id = '%s' and subject_code = '1405' ";
    $data = $db->query($sql, $companyId);
    if (!$data) {
      // 莫名的bug
      return $this->bad("科目1405没有初始化");
    }
    $tableName = $data[0]["db_table_name_prefix"] . "_detail";

    $voucherSummary = "业财融合: 本记录由进销存库存建账数据导入";
    foreach ($dataInv as $v) {
      $goodsId = $v["goods_id"];
      $c = $v["balance_count"];
      $p = $v["balance_price"];
      $m = $v["balance_money"];

      $sql = "select g.code, g.name, g.spec, u.name as unit_name
              from t_goods g, t_goods_unit u
              where g.id = '%s' and g.unit_id = u.id";
      $data = $db->query($sql, $goodsId);
      if (!$data) {
        // 莫名的bug
        continue;
      }
      $goodsCode = $data[0]["code"];
      $goodsName = $data[0]["name"];
      $goodsSpec = $data[0]["spec"];
      if ($goodsSpec) {
        $goodsName .= "/{$goodsSpec}";
      }
      $unitName = $data[0]["unit_name"];
      $goodsName .= "/{$unitName}";

      // 删除明细账中的物料信息
      $sql = "delete from {$tableName}
              where je_number = -1000 and x_goods_id = '%s' ";
      $rc = $db->execute($sql, $goodsId);
      if ($rc === false) {
        return $this->sqlError(__METHOD__, __LINE__);
      }

      // 明细账插入物料信息
      $accId = $this->newId();
      $sql = "insert into {$tableName}(
                acc_id, company_id, sub_acc_level, acc_flag,
                subject_code, voucher_dt, voucher_year, voucher_month,
                voucher_word, je_number, 
                x_db_cnt, x_db_price, acc_db, 
                x_cr_cnt, x_cr_price, acc_cr,
                x_balance_cnt, x_balance_price, acc_balance, acc_balance_dbcr, 
                x_warehouse, x_warehouse_name, x_warehouse_id,
                x_goods, x_goods_name, x_goods_id,
                voucher_summary
              ) values(
                '%s', '%s', 2, -1,
                '1405', '%s', %d, %d,
                '', -1000,
                %f, %f, %f,
                null, null, null,
                %f, %f, %f, '借方',
                '%s', '%s', '%s',
                '%s', '%s', '%s',
                '%s'
              )";
      $rc = $db->execute(
        $sql,
        $accId,
        $companyId,
        $accDT,
        $accYear,
        $accMonth,
        $c,
        $p,
        $m,
        $c,
        $p,
        $m,
        $warehouseCode,
        $warehouseName,
        $warehouseId,
        $goodsCode,
        $goodsName,
        $goodsId,
        $voucherSummary,
      );
      if ($rc === false) {
        return $this->sqlError(__METHOD__, __LINE__);
      }
    }

    $log = "{$companyName} - 由库存建账数据导入财务总账建账数据";

    // 操作成功
    $params["log"] = $log;
    return null;
  }
}
